package com.juku2024.juku.network.retrofit

import android.text.TextUtils
import com.juku2024.juku.BuildConfig
import com.juku2024.juku.base.BaseApplication
import com.juku2024.juku.tools.AppUtils
import com.juku2024.juku.tools.NetworkUtils
import okhttp3.*
import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.RequestBody.Companion.toRequestBody
import okhttp3.logging.HttpLoggingInterceptor
import retrofit2.Retrofit
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory
import retrofit2.converter.gson.GsonConverterFactory
import retrofit2.converter.scalars.ScalarsConverterFactory
import java.io.File
import java.security.SecureRandom
import java.security.cert.CertificateException
import java.security.cert.X509Certificate
import java.util.concurrent.TimeUnit
import javax.net.ssl.*

class RetrofitUtils {

    //    private var BASE_URL = "http://10.10.8.114:8083/"


    // 本地测试
//    private val BASE_URL = "http://192.168.50.7:8083/"
    // 全局测试
    private val BASE_TEST_URL = "http://124.65.176.126:8882/"

    private var channel: String? = null
    private var versionCode: String? = null
    private var retrofit: Retrofit? = null
    private var okHttpClient: OkHttpClient? = null

    companion object {
        const val BASE_URL = "http://ctaid.newtvmedia.link/"
        // 系统消息URL
        const val CHECK_SYSTEM_MSG_URL = "http://ctaid.coincoinwin.com/hasnewmsg?platform=mobile-android"
        val instance: RetrofitUtils by lazy(mode = LazyThreadSafetyMode.SYNCHRONIZED) { RetrofitUtils() }
    }

    private fun getOkHttpClient(): OkHttpClient {
        if (okHttpClient == null) {
            okHttpClient = initOkHttpClient()
//            ignoreSSLCheck()
        }
        return okHttpClient!!
    }

    private fun getRetrofit(): Retrofit {
        if (retrofit == null) {
            retrofit = Retrofit.Builder()
                .baseUrl(BASE_URL)
                .client(getOkHttpClient())
                //设置 Json 转换器
                .addConverterFactory(GsonConverterFactory.create())
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .build()
        }
        return retrofit!!
    }

    fun <T> getApi(service: Class<T>): T {
        return getRetrofit().create(service)
    }


    fun <T> getApi(baseUrl: String, service: Class<T>): T {
        val retrofit = Retrofit.Builder()
            .baseUrl(baseUrl)
            .client(getOkHttpClient())
            .addConverterFactory(GsonConverterFactory.create())
            .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
            .build()
        return retrofit.create(service)
    }

    fun <T> getStringApi(service: Class<T>): T {
        val baseUrl = BASE_URL
        val retrofit = Retrofit.Builder()
            .baseUrl(baseUrl)
            .client(getOkHttpClient())
            .addConverterFactory(ScalarsConverterFactory.create())
            .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
            .build()
        return retrofit.create(service)
    }

    private fun initOkHttpClient(): OkHttpClient {
        channel = AppUtils.getChannelValue()
        versionCode = AppUtils.getVersionCode().toString()
        val readTime = 30
        val writeTime = 30
        val connectTime = 30

        val builder = OkHttpClient.Builder()
        // cache文件位置和大小
        val cacheSize = 104857600 // 100M
        val cacheDirectory = BaseApplication.context.externalCacheDir // /data/user/0/com.movies.mobiletv/cache/
        val fileCache = File(cacheDirectory, "json")
        if (!fileCache.exists()) {
            fileCache.mkdirs()
        }
        val cache = Cache(fileCache, cacheSize.toLong())
        builder.cache(cache)
        builder.connectTimeout(connectTime.toLong(), TimeUnit.SECONDS)
        builder.readTimeout(readTime.toLong(), TimeUnit.SECONDS)
        builder.writeTimeout(writeTime.toLong(), TimeUnit.SECONDS)
        builder.retryOnConnectionFailure(true)

        builder.addInterceptor { chain ->
            val originalRequest = chain.request()
//            val response = if (BaseApplication.isEmulator || NetworkUtils.isWifiProxy() || !SafeTools.checkAppSafe()) { //拦截指定地址
            val response = if (NetworkUtils.isWifiProxy()) { //拦截指定地址
                val requestBuilder = originalRequest.newBuilder()
                // 在这做所有你需要做的事情，重新产生一个 Request 送出去。
                val responseString = "{\"success\":false,\"code\":-15,\"msg\":\"请正确使用App\"}"
                val body = responseString.toRequestBody()
                val newRequest = requestBuilder.post(body).build()
                chain.proceed(newRequest)
            } else {
                chain.proceed(originalRequest)
            }
            return@addInterceptor response
        }

        builder.addInterceptor { chain ->
            val operatorType = NetworkUtils.getCellularOperatorType(BaseApplication.context)
            // 是否国内运营商 0：不是；1：是
            val o = if (operatorType == 1 || operatorType == 2 || operatorType == 3) {
                "1"
            } else {
                "0"
            }
            // 是否启用vpn 0：未使用；1：正在使用
            val v =  if (NetworkUtils.isVpnUsed()) {
                "1"
            } else {
                "0"
            }

            // 以拦截到的请求为基础建立一个新的请求对象，而后插入Header
            val requestBuilder = chain.request().newBuilder()
                .addHeader("version", versionCode ?: "0")
                .addHeader("channel", channel ?: "")
                .addHeader("platform", AppUtils.PLATFORM)
                // 是否启用vpn
                .addHeader("v", v)
                // 是否是国内运营商
                .addHeader("o", o)
                .addHeader("c", AppUtils.getCountryCode())
            if (BuildConfig.DEBUG) {
                requestBuilder.addHeader("fq", "2020")
            }
            // 开始请求
            return@addInterceptor chain.proceed(requestBuilder.build())
        }



        builder.addInterceptor(object : Interceptor {

            private fun getForceCacheRequest(request: Request): Request {
                return request.newBuilder()
                    .removeHeader("Pragma")
                    .cacheControl(CacheControl.FORCE_CACHE)
                    .build()
            }

            override fun intercept(chain: Interceptor.Chain): Response {
                val request = chain.request()
                val cacheControl = request.cacheControl
                return if (TextUtils.isEmpty(cacheControl.toString())) {
                    chain.proceed(request)
                } else {
                    val requestCache = getForceCacheRequest(chain.request())
                    var response = chain.proceed(requestCache)
                    // 先确认是否有缓存可用
                    if (response.code == 200) { // 有缓存
                        // 先确认当前缓存是否已经超时
                        if (System.currentTimeMillis() - response.receivedResponseAtMillis >= 1000 * cacheControl.maxAgeSeconds) { // 超时
                            response = chain.proceed(chain.request())
                        }
                    } else {
                        response = chain.proceed(chain.request())
                    }
                    return response
                }
            }
        })
        // 重试
        builder.addInterceptor(RetryInterceptor(3))
        if (BuildConfig.DEBUG) {
            val loggingInterceptor = HttpLoggingInterceptor()
            loggingInterceptor.level = HttpLoggingInterceptor.Level.BODY
            builder.addInterceptor(loggingInterceptor)
        }
        return builder.build()
    }




    private class RetryInterceptor(retry: Int) : Interceptor {

        private var maxRetry = 3 //最大重试次数
        private var retryNum = 0

        init {
            if (retry > 0)
                maxRetry = retry
        }

        override fun intercept(chain: Interceptor.Chain): Response {
            val request = chain.request()
            var response = chain.proceed(request)
            while (!response.isSuccessful && retryNum < maxRetry) {
                retryNum++
                response.close()
                response = chain.proceed(request)
            }
            retryNum = 0
            return response
        }
    }

    private fun ignoreSSLCheck(builder: OkHttpClient.Builder) {
        var sc: SSLContext? = null
        try {
            sc = SSLContext.getInstance("SSL")
            val trustAllCerts = arrayOf<TrustManager>(object : X509TrustManager {
                override fun getAcceptedIssuers(): Array<X509Certificate> {
                    return arrayOf()
                }

                @Throws(CertificateException::class)
                override fun checkClientTrusted(chain: Array<X509Certificate>, authType: String) {
                }

                @Throws(CertificateException::class)
                override fun checkServerTrusted(chain: Array<X509Certificate>, authType: String) {
                }
            })
            sc.init(null, trustAllCerts, SecureRandom())
        } catch (e: Exception) {
            e.printStackTrace()
        }
        val sslSocketFactory = sc?.socketFactory
        builder.sslSocketFactory(sslSocketFactory!!, object : X509TrustManager {
            override fun getAcceptedIssuers(): Array<X509Certificate> {
                return arrayOf()
            }

            @Throws(CertificateException::class)
            override fun checkClientTrusted(chain: Array<X509Certificate>, authType: String) {
            }

            @Throws(CertificateException::class)
            override fun checkServerTrusted(chain: Array<X509Certificate>, authType: String) {
            }
        })
        builder.hostnameVerifier { _, _ -> true }
    }


}